{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "fcc6cdf8",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "from torchvision import datasets,transforms,models\n",
    "import torchvision\n",
    "from torchsummary import summary\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "041fc1b3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入训练数据\n",
    "batch_size = 16\n",
    "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
    "\n",
    "trainloader = torch.utils.data.DataLoader(\n",
    "    datasets.FashionMNIST('data', train=True, download=True,\n",
    "                          transform=transforms.Compose([\n",
    "                              transforms.Resize((299, 299)),\n",
    "                              transforms.Grayscale(num_output_channels=3),\n",
    "                              transforms.ToTensor()\n",
    "                          ])),\n",
    "    batch_size=batch_size, shuffle=True)\n",
    "\n",
    "testloader = torch.utils.data.DataLoader(\n",
    "    datasets.FashionMNIST('data', train=False, download=True,\n",
    "                          transform=transforms.Compose([\n",
    "                              transforms.Resize((299, 299)),\n",
    "                              transforms.Grayscale(num_output_channels=3),\n",
    "                              transforms.ToTensor()\n",
    "                          ])),\n",
    "    batch_size=batch_size, shuffle=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "90e54918",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义模型\n",
    "class InceptionModule(nn.Module):\n",
    "    def __init__(self, in_channels, out_channels):\n",
    "        super(InceptionModule, self).__init__()\n",
    "\n",
    "        self.branch1x1 = nn.Conv2d(in_channels, out_channels[0], kernel_size=1)\n",
    "\n",
    "        self.branch3x3_1 = nn.Conv2d(in_channels, out_channels[1], kernel_size=1)\n",
    "        self.branch3x3_2 = nn.Conv2d(out_channels[1], out_channels[2], kernel_size=3, padding=1)\n",
    "\n",
    "        self.branch5x5_1 = nn.Conv2d(in_channels, out_channels[3], kernel_size=1)\n",
    "        self.branch5x5_2 = nn.Conv2d(out_channels[3], out_channels[4], kernel_size=5, padding=2)\n",
    "\n",
    "        self.branch_pool = nn.Conv2d(in_channels, out_channels[5], kernel_size=1)\n",
    "\n",
    "    def forward(self, x):\n",
    "        branch1x1 = self.branch1x1(x)\n",
    "\n",
    "        branch3x3 = self.branch3x3_1(x)\n",
    "        branch3x3 = self.branch3x3_2(branch3x3)\n",
    "\n",
    "        branch5x5 = self.branch5x5_1(x)\n",
    "        branch5x5 = self.branch5x5_2(branch5x5)\n",
    "\n",
    "        branch_pool = F.max_pool2d(x, kernel_size=3, stride=1, padding=1)\n",
    "        branch_pool = self.branch_pool(branch_pool)\n",
    "\n",
    "        outputs = [branch1x1, branch3x3, branch5x5, branch_pool]\n",
    "        return torch.cat(outputs, 1)\n",
    "\n",
    "class SimpleInceptionNet(nn.Module):\n",
    "    def __init__(self, num_classes=10):\n",
    "        super(SimpleInceptionNet, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3)\n",
    "        self.maxpool1 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n",
    "        self.conv2 = nn.Conv2d(64, 192, kernel_size=3, stride=1, padding=1)\n",
    "        self.maxpool2 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n",
    "\n",
    "        self.inception = InceptionModule(192, [64, 96, 128, 16, 32, 32])\n",
    "        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n",
    "        self.fc = nn.Linear(256, num_classes)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = self.conv1(x)\n",
    "        x = F.relu(x)\n",
    "        x = self.maxpool1(x)\n",
    "\n",
    "        x = self.conv2(x)\n",
    "        x = F.relu(x)\n",
    "        x = self.maxpool2(x)\n",
    "\n",
    "        x = self.inception(x)\n",
    "        x = self.avgpool(x)\n",
    "        x = torch.flatten(x, 1)\n",
    "        x = self.fc(x)\n",
    "        return x\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "3dc04987",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 模型初始化\n",
    "model = SimpleInceptionNet(num_classes=10).to(device)\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = optim.Adam(model.parameters(), lr=0.001)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "6ec7b798",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/5, Train Loss: 0.9918, Train Accuracy: 63.28%\n",
      "Epoch 2/5, Train Loss: 0.6562, Train Accuracy: 76.72%\n",
      "Epoch 3/5, Train Loss: 0.5765, Train Accuracy: 79.63%\n",
      "Epoch 4/5, Train Loss: 0.5356, Train Accuracy: 81.33%\n",
      "Epoch 5/5, Train Loss: 0.5057, Train Accuracy: 82.16%\n"
     ]
    }
   ],
   "source": [
    "# 对模型进行训练\n",
    "epochs = 5\n",
    "for epoch in range(epochs):\n",
    "    model.train()\n",
    "    running_loss = 0.0\n",
    "    correct = 0\n",
    "    total = 0\n",
    "    for i, data in enumerate(trainloader, 0):\n",
    "        inputs, labels = data\n",
    "        inputs, labels = inputs.to(device), labels.to(device)\n",
    "\n",
    "        optimizer.zero_grad()\n",
    "\n",
    "        outputs = model(inputs)\n",
    "        loss = criterion(outputs, labels)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "\n",
    "        running_loss += loss.item()\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        total += labels.size(0)\n",
    "        correct += (predicted == labels).sum().item()\n",
    "        \n",
    "    train_loss = running_loss / len(trainloader)\n",
    "    train_accuracy = 100 * correct / total\n",
    "    \n",
    "    print(f\"Epoch {epoch+1}/{epochs}, Train Loss: {train_loss:.4f}, Train Accuracy: {train_accuracy:.2f}%\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1b8d64d7",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
